import { EventDispatcher } from "../../event";
import { InjectableObject } from "../../inject";
import { IEventMap } from "../base/IEventMap";

class EventHandler {
    dispatcher: EventDispatcher;
    event: string;
    listener: Function;
    target: Object;

    onEventCallback(...args: any[]) {
        if (!this.listener) {
            return;
        }
        this.listener(...args);
    }
}

export class EventMap extends InjectableObject implements IEventMap {

    listeners: Array<EventHandler> = new Array;

    constructor(eventDispatcher: EventDispatcher) {
        super();

        this._dispatcher = eventDispatcher;
    }

    mapListener(dispatcher: EventDispatcher, event: string, listener: Function, target: Object, priority: number) {
        let handler: EventHandler = null;

        let i: number = this.listeners.length;

        while (i--) {
            handler = this.listeners[i];

            if (handler.dispatcher === dispatcher
                && handler.event === event
                && handler.listener === listener
                && handler.target === target) {
                return;
            }
        }

        handler = new EventHandler;
        handler.dispatcher = dispatcher;
        handler.event = event;
        handler.listener = listener;
        handler.target = target;

        this.listeners.push(handler);

        this.dispatcher.on(event, handler.onEventCallback, handler);
    }

    unmapListener(dispatcher: EventDispatcher, event: string, listener: Function, target: Object) {
        let handler: EventHandler = null;

        let i: number = this.listeners.length;

        while (i--) {
            handler = this.listeners[i];

            if (handler.dispatcher === dispatcher
                && handler.event === event
                && handler.listener === listener
                && handler.target === target) {
                dispatcher.off(event, handler.onEventCallback, target);
                this.listeners.splice(i, 1);
                return;
            }
        }
    }

    unmapListeners() {
        let handler: EventHandler = null;
        let dispatcher: EventDispatcher = null;
        while (handler = this.listeners.pop()) {
            dispatcher = handler.dispatcher;
            dispatcher.off(handler.event, handler.onEventCallback, handler.target);
        }
    }
}